package com.lenin.omena.client;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.maps.client.geocode.Geocoder;
import com.google.gwt.maps.client.geocode.LocationCallback;
import com.google.gwt.maps.client.geocode.Placemark;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.lenin.omena.client.event.DeleteUserEvent;
import com.lenin.omena.client.event.DeleteUserEventHandler;
import com.lenin.omena.client.event.SaveUserEvent;
import com.lenin.omena.client.event.SaveUserEventHandler;
import com.lenin.omena.client.event.SaveUserInfoEvent;
import com.lenin.omena.client.event.SaveUserInfoEventHandler;
import com.lenin.omena.shared.DeleteUserResult;
import com.lenin.omena.shared.SaveUserInfoResult;
import com.lenin.omena.shared.SaveUserResult;
import com.lenin.omena.shared.domain.Address;
import com.lenin.omena.shared.domain.Site;
import com.lenin.omena.shared.domain.User;
import com.lenin.omena.shared.domain.UserInfo;

public class UserInfoForm extends Composite 
	implements SaveUserEventHandler, SaveUserInfoEventHandler {

	interface MyUiBinder extends UiBinder<Widget, UserInfoForm> {
	}

	private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
	
	public enum ActionType {
		
		REGISTER_USER("Rekisteröidy"), 
		SAVE_USER_INFO("Tallenna");
		
		private String submitButtonLabel;
		
		private ActionType(String submitButtonLabel) {
			this.submitButtonLabel = submitButtonLabel;
		}
		
		public String getSubmitButtonLabel() {
			return submitButtonLabel;
		}
		
	}
	
	@UiField
	HTMLPanel statusSpan;
	
	@UiField
	TextBox userNameField;
	
	@UiField
	HTMLPanel userNameVal;
	
	@UiField
	PasswordTextBox passwordField;
	
	@UiField
	HTMLPanel passwordVal;
	
	@UiField
	PasswordTextBox confirmPasswordField;
	
	@UiField
	HTMLPanel confirmPasswordVal;
	
	@UiField
	TextBox emailField;
	
	@UiField
	HTMLPanel emailVal;
	
	@UiField
	TextBox phoneNumberField;
	
	@UiField
	TextBox addressField;
	
	@UiField
	HTMLPanel addressVal;
	
	@UiField
	Button submitButton;
	
	@UiField
	HTMLPanel removeAccountSpan;
	
	private Button removeAccountButton;
	
	private UserInfo userInfo;
	
	private ActionType actionType;
	
	
	public UserInfoForm() {
		this(null, ActionType.REGISTER_USER);
	}
	
	
	public UserInfoForm(UserInfo userInfo, ActionType actionType) {

		initWidget(uiBinder.createAndBindUi(this));
		
		this.userInfo = userInfo;
		this.actionType = actionType;
		
		
		SaveUserEvent.register(AppleMarket.getEventBus(), this);
		SaveUserInfoEvent.register(AppleMarket.getEventBus(), this);
		
		submitButton.setText(actionType.getSubmitButtonLabel());
		
		if(actionType == ActionType.SAVE_USER_INFO) {
			
			removeAccountButton = new Button("*** POISTA PROFIILI ***");
			removeAccountSpan.add(removeAccountButton);
			
			removeAccountButton.addClickHandler(new ClickHandler() {
				
				public void onClick(ClickEvent event) {
					
					AppleMarket.doDeleteUser(AppleMarket.getUserContext().getUser());
					
				}
				
			});
			
		}
		
		setFields();
		
	}
	
	
	private void setFields() {
		
		if(userInfo != null) {
			userNameField.setText(userInfo.getUserName());
			passwordField.setText(userInfo.getPassword());
			emailField.setText(userInfo.getEmail());
			addressField.setText(userInfo.getSiteAddress().getAddress());
		}
			
		
	}
	
	
	private boolean validateFields() {
		
		boolean ok = true;
		
		userNameVal.getElement().setInnerHTML("");
		passwordVal.getElement().setInnerHTML("");
		confirmPasswordVal.getElement().setInnerHTML("");
		emailVal.getElement().setInnerHTML("");
		addressVal.getElement().setInnerHTML("");
		
		String userName = userNameField.getText();
		
		if(userName.length() < 3 || userName.length() > 24) {
			setValidationMessage(userNameVal, "Käyttäjätunnuksen pitää olla 3-24 merkkiä pitkä.");
			ok = false;
		}
		
		if(hasIllegalChars(userName)) {
			setValidationMessage(userNameVal, "Käyttäjätunnus voi sisältää vain merkkejä 0-9, A-Z ja a-z.");
			ok = false;
		}
		
		String password = passwordField.getText();
		
		if(password.length() < 3 || password.length() > 24) {
			setValidationMessage(passwordVal, "Salasanan pitää olla 3-24 merkkiä pitkä.");
			ok = false;
		}
		
		if(hasIllegalChars(password)) {
			setValidationMessage(passwordVal, "Salasana voi sisältää vain merkkejä 0-9, A-Z ja a-z.");
			ok = false;
		}
		
		
		String confirmPassword = confirmPasswordField.getText();
		
		if(!confirmPassword.equals(password)) {
			setValidationMessage(confirmPasswordVal, "Salasanan ja sen varmistuksen täytyy olla samat.");
			ok = false;
		}
		
		String email = emailField.getText();
		
		int atIndex = email.indexOf("@");
		int dotIndex = email.indexOf(".");
		
		if(atIndex < 1 || dotIndex < 3 || dotIndex > email.length()-3 || atIndex > dotIndex) {
			setValidationMessage(emailVal, "Virheellinen sähköpostiosoite.");
			ok = false;
		}
		
		
		return ok;
		
	}
	
	
	private boolean hasIllegalChars(String str) {
		
		char[] chars = str.toCharArray();
		for(char c : chars) {
			
			int i = (int)c;
			
			if(! ( (i >= 48 && i <= 57) || (i >= 65 && i <= 90) || (i >= 97 && i <= 122) ) )
				return true;
			
		}
		
		return false;
		
	}
	
	
	@UiHandler("submitButton")
	void handleClick(ClickEvent event) {
		
		if(!validateFields())
			return;
		
		if(userInfo == null)
			userInfo = new UserInfo();
		
		String userName = userNameField.getText();
		userInfo.setUserName(userName);
		
		String password = passwordField.getText();
		userInfo.setPassword(password);
		
		String email = emailField.getText();
		userInfo.setEmail(email);
		
		final String addressValue = addressField.getText();
		
		Geocoder geoCoder = new Geocoder(); //AppleMarket.getGeocoder();
		
		String message =
				"Tarkistetaan osoitetta...";
		setStatusText(message, "#666");
		
		geoCoder.getLocations(addressValue, new LocationCallback() {
			
			public void onSuccess(JsArray<Placemark> locations) {
				
				if(locations.length() == 1) {
					
					Placemark location = locations.get(0);
					
					String country = location.getCountry();
					
					if(!country.equals("FI")) {
						setValidationMessage(addressVal, "Ilmoittamasi osoite ei ole Suomessa.");
						return;
					}
					
					LatLng latLng = location.getPoint();
					
					Address address = new Address();
					address.setAddress(addressValue);
					address.setLatitude(latLng.getLatitude());
					address.setLongitude(latLng.getLongitude());
					
					userInfo.setSiteAddress(address);
					
					if(actionType == ActionType.REGISTER_USER) {
						
						Site site = new Site();
						site.setAddress(address);
						site.setLongitude(latLng.getLongitude());
						site.setLatitude(latLng.getLatitude());
						
						User user = new User();
						user.setSite(site);
						user.setUserInfo(userInfo);
						
						String message =
								"Rekisteröinti käynnissä...";
						setStatusText(message, "#666");
						
						AppleMarket.doSaveUser(user);
						
					} else {
						
						User user = AppleMarket.getUserContext().getUser();
						user.setUserInfo(userInfo);
						
						String message =
								"Tietojen tallennus käynnissä...";
						setStatusText(message, "#666");
						
						AppleMarket.doSaveUserInfo(user, userInfo);
						
					}
					
					
				} else {
					
					if(locations.length() == 0) {
						setValidationMessage(addressVal, "Osoitetta ei löytynyt");
					} else {
						setValidationMessage(addressVal, "Useita osoitetietoja löytynyt. Tarkenna osoitetta.");
					}
					
					setStatusText("", "#000");
					
				}
				
			}
			
			public void onFailure(int status) {
				
				String message =
						"Virhe osoitteen tarkistuksessa. Virhekoodi: "+status;
				setStatusText(message, "#800");
			
			}
			
			
		});
		
		
		
	}
	
	
	@Override
	public void onSaveUser(SaveUserEvent event) {
	
		SaveUserResult result = event.getResult();
		
		User user = result.getUser();
		
		if(result.getStatus() == 0) {
			
			String message =
					"Käyttäjä rekisteröity.";
			setStatusText(message, "#080");
		
		} else if (result.getStatus() == -1) {
			
			String message =
					"Virhe käyttäjän rekisteröinnissä.";
			setStatusText(message, "#800");
		
		} else if(result.getStatus() == 2) {
			
			String message =
					"Käyttäjätunnus on jo varattu. Valitse toinen käyttäjätunnus.";
			setStatusText(message, "#800");
			
		}
		
		
	}
	
	
	@Override
	public void onSaveUserInfo(SaveUserInfoEvent event) {
		
		SaveUserInfoResult result = event.getResult();
		
		if(userInfo != null)
			userInfo = result.getUserInfo();
		
		if(result.getStatus() == 0) {
			
			String message =
					"Käyttäjätiedot tallennettu.";
			setStatusText(message, "#080");
		
		} else {
			
			String message =
					"Virhe käyttäjätietojen tallennuksessa.";
			setStatusText(message, "#800");
		
		}
		
	}
	
	
	private void setStatusText(String text, String color) {
		
		statusSpan.getElement().setAttribute("style", "color: "+color);
		statusSpan.getElement().setInnerHTML(text);
		
	}
	
	private void setValidationMessage(HTMLPanel span, String message) {
		span.getElement().setInnerHTML(message);
	}

}
